/*
 * 
 * LegendShop 多用户商城系统
 * 
 *  版权所有,并保留所有权利。
 * 
 */
package com.legendshop.oa.dao.impl;

import com.legendshop.dao.SQLOperation;
import com.legendshop.dao.impl.GenericDaoImpl;
import com.legendshop.dao.support.PageSupport;
import com.legendshop.dao.support.QueryMap;
import com.legendshop.dao.support.SimpleSqlQuery;
import com.legendshop.oa.constants.Constants;
import com.legendshop.oa.constants.EventOperationTypeEnum;
import com.legendshop.oa.constants.EventTypeEnum;
import com.legendshop.oa.constants.TaskStatusEnum;
import com.legendshop.oa.dao.EventDao;
import com.legendshop.oa.dao.ProjectDao;
import com.legendshop.oa.dao.TaskDao;
import com.legendshop.oa.dao.TaskEstimateDao;
import com.legendshop.oa.dto.*;
import com.legendshop.oa.model.Task;
import com.legendshop.oa.model.TaskEstimate;
import com.legendshop.oa.security.UserDetail;
import com.legendshop.util.AppUtils;
import com.legendshop.util.DateUtil;
import com.legendshop.dao.sql.ConfigCode;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * The Class TaskDaoImpl. Dao实现类
 */

public class TaskDaoImpl extends GenericDaoImpl<Task, Long> implements TaskDao {

	private EventDao eventDao;

	private String STATUS_SQL = "statusSQL"; // 组装SQL用

	private String TIME_RANGE_SQL = "timeRangeSQL";// 组装SQL用

	private TaskEstimateDao taskEstimateDao;

	private ProjectDao projectDao;
	/**
	 * 根据Id获取
	 */
	public Task getTask(Long id) {
		String sql = "SELECT t.*, (SELECT real_name FROM ls_admin_user u WHERE t.assignedTo = u.name) AS assignedtoRealName,(SELECT SUM(consumed) FROM ls_taskestimate WHERE task_id = t.id) AS totalConsumed FROM ls_task t where t.id = ?";
		return get(sql, Task.class, id);
	}

	@Override
	public Task getTaskById(Long id) {
		return getById(id);
	}

	/**
	 * 删除
	 */
	public int deleteTask(Task task) {
		return delete(task);
	}

	/**
	 * 保存
	 */
	public Long saveTask(Task task, UserDetail ud) {
		Long taskId = save(task);

		eventDao.saveEvent(ud, taskId, null, EventTypeEnum.TASK, EventOperationTypeEnum.CREATE);
		return taskId;
	}

	/**
	 * 更新
	 */
	public int updateTask(Task task) {
		return update(task);
	}

	/**
	 * 获取任务列表,排除已经完成的项目
	 */
	@Override
	public PageSupport<Task> getTask(TaskQueryDto taskQueryDto) {
		SimpleSqlQuery query = new SimpleSqlQuery(Task.class, taskQueryDto.getCurPageNO());
		query.setPageSize(taskQueryDto.getPageSize());
		QueryMap map = new QueryMap();
		if(AppUtils.isBlank(taskQueryDto.getUserName())){
			throw new RuntimeException("userName can not empty");
		}
		map.put("userName", taskQueryDto.getUserName());
		map.put("id", taskQueryDto.getId());
		map.put("projectId", taskQueryDto.getProjectId());
		map.put("planId", taskQueryDto.getPlanId());
		map.put("moudleId", taskQueryDto.getModuleId());
		map.put("type", taskQueryDto.getType());
		map.put("priority", taskQueryDto.getPriority());
		map.put("openedby", taskQueryDto.getOpenedby());
		map.put("assignedto", taskQueryDto.getAssignedto());
		map.put("finishedby", taskQueryDto.getFinishedby());
		map.put("canceledby", taskQueryDto.getCanceledby());
		map.put("closedby", taskQueryDto.getClosedby());
		map.put("createBy", taskQueryDto.getCreateBy());

		if (taskQueryDto.getStatus() != null) {
			map.put(STATUS_SQL, " and t1.status = ?");
			map.put("status", taskQueryDto.getStatus());
		} else {
			// map.put(STATUS_SQL, " and t1.status < 4"); //默认不传值则为没有结束状态之前的任务
		}

		// 根据时间来筛选
		if (taskQueryDto.getSearchTimeMode() != null && taskQueryDto.getStartDate() != null && taskQueryDto.getEndDate() != null) {
			map.put("startTime", taskQueryDto.getStartDate());
			map.put("endTime", taskQueryDto.getEndDate());
			if (SearchTimeModeEnum.CREATE_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.createTime >= ? and t1.createTime < ?");
			} else if (SearchTimeModeEnum.START_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.realStarted >= ? and t1.realStarted < ?");
			} else if (SearchTimeModeEnum.ASSIGN_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.assignedDate >= ? and t1.assignedDate < ?");
			} else if (SearchTimeModeEnum.CLOSE_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.closedDate >= ? and t1.closedDate < ?");
			} else if (SearchTimeModeEnum.CANCEL_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.canceledDate >= ? and t1.canceledDate < ?");
			} else if (SearchTimeModeEnum.FINISH_TIME.value().equals(taskQueryDto.getSearchTimeMode())) {
				map.put(TIME_RANGE_SQL, " and t1.finishedDate >= ? and t1.finishedDate < ?");
			}

		}

		map.like("name", taskQueryDto.getName());
		
//		//判断是否为外部排序 TODO 需要删除
//		if (taskQueryDto.getSortResult().isSortExternal()) {
//			map.put(Constants.ORDER_INDICATOR,  taskQueryDto.getSortResult().parseSeq());
// 		}

		String querySql = ConfigCode.getInstance().getCode("oa.getTask", map);
		String sqlCount = ConfigCode.getInstance().getCode("oa.getTaskCount", map);

		map.remove("statusSQL");// 前面加入了status，防止为空的情况出现
		map.remove("timeRangeSQL");
		map.remove(Constants.ORDER_INDICATOR);
		query.setParam(map.toArray());
		query.setQueryString(querySql);
		query.setAllCountString(sqlCount);

		return querySimplePage(query);
	}

	/**
	 * 分配任务
	 */
	@Override
	public boolean assignUpdateTask(Long taskId, TaskAssignDto taskAssignDto, UserDetail ud) {
		Task task = getTaskById(taskId);
		Date date = new Date();
		int result = this.update(
				"update ls_task set assignedTo = ?,left_hours =?, assignedDate = ?,remark = ? where id = ?",
				taskAssignDto.getUserName(), taskAssignDto.getLeftHours(), date, taskAssignDto.getRemark(), taskId);
		// 记录历史
		if (result > 0) {
			String data = "";
			String title = "";
			boolean changed = false;
			if (taskAssignDto.getUserName() != null && !taskAssignDto.getUserName().equals(task.getAssignedto())) {
				data = data + "修改了'指派给'， 旧值为" + task.getAssignedto() + ",新值为" + taskAssignDto.getUserName() + ";";
				title = ud.getRealName() + " " + data;
				changed = true;
			}

			if (AppUtils.isNotBlank(taskAssignDto.getLeftHours())
					&& !taskAssignDto.getLeftHours().equals(task.getLeftHours())) {// 修改了剩余时间
				data = data + " 修改了'预计剩余'， 旧值为" + task.getLeftHours() + ",新值为" + taskAssignDto.getLeftHours();
				changed = true;
			}

			if (AppUtils.isNotBlank(taskAssignDto.getRemark())) {// 修改了剩余时间
				data = data + " 修改了'备注'" + ",新值为" + taskAssignDto.getRemark();
				changed = true;
			}

			if (changed) {
				if (AppUtils.isNotBlank(title)) {
					eventDao.saveEvent(ud, taskId, title, data, EventTypeEnum.TASK, EventOperationTypeEnum.EDIT);
				} else {
					eventDao.saveEvent(ud, taskId, data, EventTypeEnum.TASK, EventOperationTypeEnum.EDIT);
				}
			}
		}
		return result > 0;
	}

	/**
	 * 开始任务
	 */
	@Override
	public boolean startUpdateTask(Long taskId, TaskStartDto taskStartDto, UserDetail ud) {
		Task task = getTaskById(taskId);
		int status = TaskStatusEnum.PROCESSING.value();
		if (taskStartDto.getLeftHours() != null && taskStartDto.getLeftHours().intValue() == 0) {
			status = TaskStatusEnum.FINISH.value();
		}
		//更新任务
		int result = this.update(
				"update ls_task set status = ?, realStarted = ?,left_hours =?, remark = ? where id = ?", status,
				taskStartDto.getRealStarted(), taskStartDto.getLeftHours(), taskStartDto.getRemark(), taskId);
		// 记录历史
		if (result > 0) {
			String data = "";
			boolean changed = false;

			if (AppUtils.isNotBlank(taskStartDto.getRealStarted())) {// 修改了剩余时间
				data = data + " 修改了'实际开始'，" + ",新值为"
						+ DateUtil.DateToString(taskStartDto.getRealStarted(), DateUtil.CM_LONG_DATE_FORMAT);
				changed = true;
			}

			if (AppUtils.isNotBlank(taskStartDto.getLeftHours())
					&& !taskStartDto.getLeftHours().equals(task.getLeftHours())) {// 修改了剩余时间
				data = data + " 修改了'预计剩余'， 旧值为" + task.getLeftHours() + ",新值为" + taskStartDto.getLeftHours();
				changed = true;
			}

			if (AppUtils.isNotBlank(taskStartDto.getRemark())) {// 修改了剩余时间
				data = data + " 修改了'备注'" + ",新值为" + taskStartDto.getRemark();
				changed = true;
			}

			if (AppUtils.isNotBlank(taskStartDto.getConsumed()) && taskStartDto.getConsumed() > 0) {
				data = data + " 消耗工时为" + taskStartDto.getConsumed();
				changed = true;
				// 记录日志
				TaskEstimate taskEstimate = new TaskEstimate();
				taskEstimate.setConsumed(taskStartDto.getConsumed());
				taskEstimate.setDate(taskStartDto.getRealStarted());
				taskEstimate.setLeftHours(taskStartDto.getLeftHours());
				taskEstimate.setTaskId(taskId);
				taskEstimate.setUserName(ud.getUsername());
				taskEstimate.setProjectId(task.getProjectId());
				String work = "启动任务";
				if (AppUtils.isNotBlank(taskStartDto.getRemark())) {
					taskEstimate.setWork(work + "。 " + taskStartDto.getRemark());
				} else {
					taskEstimate.setWork(work);
				}

				taskEstimateDao.saveTaskEstimate(taskEstimate);
			}

			if (changed) {
				eventDao.saveEvent(ud, taskId, data, EventTypeEnum.TASK, EventOperationTypeEnum.START);
			}
		}
		return result > 0;
	}

	/**
	 * 结束任务
	 */
	@Override
	public boolean finishUpdateTask(Long taskId, TaskFinishDto taskFinishDto, UserDetail ud) {
		Task task = getTaskById(taskId);
		int result = this.update(
				"update ls_task set status = ?,finishedBy = ?, finishedDate = ?,assignedTo =?, remark = ? where id = ?",
				TaskStatusEnum.FINISH.value(), ud.getUsername(), new Date(), taskFinishDto.getUserName(),
				taskFinishDto.getRemark(), taskId);
		// 记录历史
		if (result > 0) {
			String data = task.getName() + " ";
			if (taskFinishDto.getUserName() != null && !taskFinishDto.getUserName().equals(task.getAssignedto())) {
				data = data + "修改了'指派给'， 旧值为" + task.getAssignedto() + ",新值为" + taskFinishDto.getUserName() + ";";
			}

			if (AppUtils.isNotBlank(taskFinishDto.getRemark())) {// 修改了剩余时间
				data = data + " 修改了'备注'" + ",新值为" + taskFinishDto.getRemark();
			}
			
			
			if (AppUtils.isNotBlank(taskFinishDto.getConsumed()) && taskFinishDto.getConsumed() > 0) {
				data = data + " 消耗工时为" + taskFinishDto.getConsumed();
				// 记录日志
				TaskEstimate taskEstimate = new TaskEstimate();
				taskEstimate.setConsumed(taskFinishDto.getConsumed());
				taskEstimate.setDate(taskFinishDto.getFinishedDate());
				taskEstimate.setLeftHours(0d);
				taskEstimate.setTaskId(taskId);
				taskEstimate.setUserName(ud.getUsername());
				taskEstimate.setProjectId(task.getProjectId());
				String work = "完成任务";
				if (AppUtils.isNotBlank(taskFinishDto.getRemark())) {
					taskEstimate.setWork(work + "。 " + taskFinishDto.getRemark());
				} else {
					taskEstimate.setWork(work);
				}

				taskEstimateDao.saveTaskEstimate(taskEstimate);
			}
			

			eventDao.saveEvent(ud, taskId, data, EventTypeEnum.TASK, EventOperationTypeEnum.FINISH);
		}
		return result > 0;
	}

	/**
	 * 关闭任务
	 */
	@Override
	public boolean closeUpdateTask(Long taskId, TaskCloseDto taskCloseDto, UserDetail ud) {
		int result = this.update("update ls_task set status = ?,closedBy = ?, closedDate = ?, remark = ? where id = ?",
				TaskStatusEnum.CLOSE.value(), ud.getUsername(), new Date(), taskCloseDto.getRemark(), taskId);
		// 记录历史
		if (result > 0) {
			String data = "";

			if (AppUtils.isNotBlank(taskCloseDto.getRemark())) {// 修改了剩余时间
				data = data + " 修改了'备注'" + ",新值为" + taskCloseDto.getRemark();
			}
			eventDao.saveEvent(ud, taskId, data, EventTypeEnum.TASK, EventOperationTypeEnum.CLOSE);
		}
		return result > 0;
	}

	@Override
	public boolean cancelUpdateTask(Long taskId, TaskCancelDto taskCancelDto, UserDetail ud) {
		int result = this.update(
				"update ls_task set status = ?,canceledBy = ?, canceledDate = ?, remark = ? where id = ?",
				TaskStatusEnum.CANCEL.value(), ud.getUsername(), new Date(), taskCancelDto.getRemark(), taskId);
		// 记录历史
		if (result > 0) {
			String data = "";
			if (AppUtils.isNotBlank(taskCancelDto.getRemark())) {// 修改了剩余时间
				data = data + " 修改了'备注'" + ",新值为" + taskCancelDto.getRemark();
			}
			eventDao.saveEvent(ud, taskId, data, EventTypeEnum.TASK, EventOperationTypeEnum.CANCEL);
		}
		return result > 0;
	}

	@Override
	public boolean saveTaskEstimate(Task task, List<TaskEstimateDto> taskEstimateList, UserDetail ud) {
		List<TaskEstimate> entities = new ArrayList<TaskEstimate>();
		for (TaskEstimateDto dto : taskEstimateList) {
			TaskEstimate te = new TaskEstimate();
			te.setConsumed(dto.getTaskestimate());
			te.setDate(dto.getDate());
			te.setLeftHours(dto.getLeftHours());
			te.setProjectId(task.getProjectId());
			te.setTaskId(task.getId());
			te.setUserName(ud.getUsername());
			te.setWork(dto.getRemark());
			entities.add(te);
		}

		if (AppUtils.isNotBlank(entities)) {
			taskEstimateDao.saveTaskEstimate(entities);
		}
		return true;
	}

	@Override
	public boolean saveTaskEstimate(Task task, TaskEstimateDto dto, UserDetail ud) {
		if(AppUtils.isNotBlank(dto.getTaskestimate()) && dto.getTaskestimate() > 0){
			TaskEstimate te = new TaskEstimate();
			te.setConsumed(dto.getTaskestimate());
			te.setDate(dto.getDate());
			te.setLeftHours(dto.getLeftHours());
			te.setProjectId(task.getProjectId());
			te.setTaskId(task.getId());
			te.setUserName(ud.getUsername());
			te.setWork(dto.getRemark());
			taskEstimateDao.saveTaskEstimate(te);
			return true;
		}
		return false;
	}

	public void setTaskEstimateDao(TaskEstimateDao taskEstimateDao) {
		this.taskEstimateDao = taskEstimateDao;
	}

	public void setEventDao(EventDao eventDao) {
		this.eventDao = eventDao;
	}

	@Override
	public List<Select2Dto> queryList(Long projectId,Date startDate, Date endDate, String userName, String q, Integer pageSize, Integer currPage) {
		int offset = (currPage - 1) * pageSize;
		QueryMap map = new QueryMap();
		map.put("projectId", projectId);
		map.put("assignedTo", userName);
		map.like("taskName", q);
//不再记录时间
		if(startDate != null && endDate != null){
			map.put("startDate", startDate);
			map.put("endDate", endDate);
			map.put("InCludeNull", "OR t.estStarted IS NULL OR t.deadline IS NULL)"); //拼接SQL，需要和xml中的sql配合，包括不写开始结束时间的任务
		}
		SQLOperation operation = ConfigCode.getInstance().getCodeParameter("oa.taskList", map);
		return queryLimit(operation.getSql(), Select2Dto.class, offset, pageSize, operation.getParams());
	}

	@Override
	public int taskCount(Long projectId, Date startDate, Date endDate, String userName, String q) {
		QueryMap map = new QueryMap();
		map.put("projectId", projectId);
		map.put("assignedTo", userName);
		map.like("taskName", q);
		map.put("startDate", startDate);
		map.put("endDate", endDate);
		String countSql = ConfigCode.getInstance().getCode("oa.taskListCount", map);
		return get(countSql, Integer.class, map.toArray());
	}

	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}

}
